﻿namespace TestServer
{
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.IO;
    using System.Drawing;
    using PInvoke;

    internal class Program
    {
        // P/Invoke to lock the workstation
        [DllImport("user32.dll")]
        public static extern bool LockWorkStation();

        // P/Invoke to unlock the workstation (only available on Windows 10 or later, and requires user input)
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool UnlockWindowStation(IntPtr hWnd);

        // P/Invoke to get system parameters
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool SystemParametersInfo(int uAction, int uParam, ref RECT lpvParam, int fuWinIni);


        static string GetLocalIPAddress()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork) // IPv4
                {
                    return ip.ToString();
                }
            }
            throw new Exception("No network adapters with an IPv4 address in the system!");
        }

        static void Shutdown(int secondsUntilShutdown)
        {
            // 使用 ProcessStartInfo 类来启动进程
            ProcessStartInfo psi = new ProcessStartInfo("shutdown", "/s /t " + secondsUntilShutdown.ToString());
            psi.CreateNoWindow = true;
            psi.UseShellExecute = false;
            // 创建一个新的进程
            Process.Start(psi);
        }

        static void Log(string message)
        {
            string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); // 获取当前时间戳
            string logMessage = $"[{timestamp}] {message}"; // 构造包含时间戳的日志消息
            using (StreamWriter writer = new StreamWriter("log.txt", true))
            {
                writer.WriteLine(logMessage);
            }
        }

        static void Main(string[] args)
        {
            string ipAddress = GetLocalIPAddress(); // 可以替换为自己的 IP
            int port = 12345; // 监听的端口

            TcpListener server = new TcpListener(IPAddress.Parse(ipAddress), port);
            server.Start();
            Log("Server started, waiting for client...");

            while (true)
            {
                TcpClient client = server.AcceptTcpClient();
                Log("Client connected.");

                NetworkStream stream = client.GetStream();
                byte[] buffer = new byte[256];
                int bytesRead;

                while (true)
                {
                    try
                    {
                        bytesRead = stream.Read(buffer, 0, buffer.Length);
                        if (bytesRead == 0)
                        {
                            // 连接关闭
                            break;
                        }


                        string request = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                        Log("Received request: " + request);


                        if (request.Equals("lock", StringComparison.OrdinalIgnoreCase))
                        {
                            LockWorkStation(); // 锁定桌面
                            Log("Desktop locked.");
                        }
                        else if (request.Equals("unlock", StringComparison.OrdinalIgnoreCase))
                        {
                            // 解锁桌面的代码，这需要与用户交互（例如按下Ctrl+Alt+Del等）
                            // 在此例中，我们不能直接通过API实现解锁，必须依赖用户手动解锁
                            Log("Unlock operation is not directly possible.");
                        }
                        else if (request.Equals("shutdown", StringComparison.OrdinalIgnoreCase))
                        {
                            Shutdown(0); // 立刻关机
                        }
                        else if (request.Contains("shutdownplan", StringComparison.OrdinalIgnoreCase))
                        {
                            try
                            {
                                string[] parts = request.Split('_');
                                if (parts.Length != 3)
                                {
                                    throw new ArgumentException("输入字符串格式错误");
                                }
                                string command = parts[0];
                                bool isShutdown = bool.Parse(parts[1]);
                                string[] timeParts = parts[2].Split(':');
                                // 使用 DateTime 存储关机时间
                                DateTime shutdowntime = new DateTime(
                                    DateTime.Now.Year,
                                    DateTime.Now.Month,
                                    DateTime.Now.Day,
                                    int.Parse(timeParts[0]),
                                    int.Parse(timeParts[1]),
                                    int.Parse(timeParts[2])
                                );


                                Log($"Command: {command}");
                                Log($"Is Shutdown: {isShutdown}");
                                Log($"Shutdown Time: {shutdowntime.ToString("HH:mm:ss")}");


                                if (isShutdown)
                                {
                                    // 计算从当前时间到关机时间的时间差（以毫秒为单位）
                                    DateTime now = DateTime.Now;
                                    if (shutdowntime < now)
                                    {
                                        // 如果关机时间已经过去，则将其设置为明天
                                        shutdowntime = shutdowntime.AddDays(1);
                                    }
                                    TimeSpan timeUntilShutdown = shutdowntime - now;
                                    int millisecondsUntilShutdown = (int)timeUntilShutdown.TotalMilliseconds / 1000;


                                    // 使用 Windows 的 shutdown 命令
                                    Shutdown(millisecondsUntilShutdown);
                                }
                                else
                                {
                                    // 取消关机
                                    Process.Start("shutdown", "/a");
                                }
                            }
                            catch (ArgumentException ex)
                            {
                                Log($"解析错误: {ex.Message}");
                            }
                        }
                        else if (request.Equals("snapshot", StringComparison.OrdinalIgnoreCase))
                        {
                            try
                            {
                                // 获取屏幕的大小
                                RECT rect = new RECT();
                                SystemParametersInfo(0x0030, 0, ref rect, 0);
                                int screenWidth = rect.right - rect.left;
                                int screenHeight = rect.bottom - rect.top;


                                // 创建位图
                                Bitmap screenshot = new Bitmap(screenWidth, screenHeight);
                                using (Graphics g = Graphics.FromImage(screenshot))
                                {
                                    // 复制屏幕内容到位图
                                    g.CopyFromScreen(rect.left, rect.top, 0, 0, new System.Drawing.Size(screenWidth, screenHeight));
                                }


                                // 将图像保存为字节数组
                                MemoryStream ms = new MemoryStream();
                                screenshot.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                                byte[] imageBytes = ms.ToArray();


                                // 发送图像长度
                                byte[] lengthBytes = BitConverter.GetBytes(imageBytes.Length);
                                stream.Write(lengthBytes, 0, lengthBytes.Length);
                                // 发送图像数据
                                stream.Write(imageBytes, 0, imageBytes.Length);

                                screenshot.Dispose();
                                ms.Close();
                            }
                            catch (Exception ex)
                            {
                                Log($"Error sending snapshot: {ex.Message}");
                                // 发送错误消息给客户端
                                byte[] errorBytes = Encoding.UTF8.GetBytes($"Error: {ex.Message}");
                                stream.Write(errorBytes, 0, errorBytes.Length);
                            }
                        }
                        else
                        {
                            Log("Invalid request.");
                        }
                    }
                    catch (IOException ex)
                    {
                        Log($"Error reading from stream: {ex.Message}");
                        break;
                    }
                }

                client.Close();
            }
        }
    }
}
